// 类本身就可以充当类型， 可以描述实例（类类型）
// ts要求所有的属性必须先声明再使用 （采用修饰符来声明）
// class Circle {
//     public x!:number;
//     public y!:number;
//     constructor(x:number, y:number = 100){ // 构造函数就是函数，用法同函数
//         this.x = x
//         this.y = y
//     }
// }

// public 公开属性（父， 子，外界都能访问）默认就是public
// protected 受保护的（父， 子）
// private 私有属性
// readonly  仅读属性 只能初始化的时候赋值，后续不能修改 类似const
/**
 * class Animal {
    constructor(public readonly name: string, public age: number){
        this.name = "aaaaa"
    }
}
class Cat extends Animal {
    constructor(name: string, age: number) {
        super(name, age)
    }
}
const animal = new Animal('xiaowugui', 110);
console.log(animal);
const tom = new Cat("Tom", 18);
console.log(tom['name']); **/  // 使用此方式可以访问私有属性 绕过ts检测

// 类的功能 主要是实例属性，原型属性，静态属性，属性访问器
// 类中的Object.defineProperty === 属性访问器
class Animal{
    static habitat = '地球';
    static getHabitat() {
        return this.habitat;
    }
    private _sound: string = '';
    constructor(public name: string, public age: number){}
    get sound() {
        return this._sound;
    }
    set sound(value: string) {
        this._sound = value;
    }
    eat(food:string) {
        console.log(`正在吃${food}`);
    }
}
class Cat extends Animal {
    constructor(name: string, age: number){
        super(name, age)
    }
    static getHabitat() {
        console.log('在家中');
        return super.getHabitat();
    }
    eat(){ //子类重写父类 要保证兼容父类的类型
     super.eat('鱼儿');
     return 'abc';
    }
}

let animal = new Cat('tom', 10);
animal.sound = "喵喵"; // 属性访问器
console.log(animal.sound);
console.log(Cat.getHabitat());
animal.eat();
// super 是指向实例,指向父类
// 原型方法

class Singleton {
    private static instance = new Singleton(); 
    private constructor(){}
    static getInstance() {
        return this.instance
    }
}
let ins1 = Singleton.getInstance();
let ins2 = Singleton.getInstance();
console.log(ins1 === ins2);
// 抽象类
// 1.不能被new
// 2.抽象类中可以创建抽象属性和方法，让子类来实现，但是静态方法，属性不可以
// 3.抽象类中可以拥有具体的实现
abstract class Person {
   static habitat = "地球";
   abstract eat():void; // 没有具体实现 一般描述原型方法
   abstract play:()=>void; // 一般 这种情况描述的是实例方法
   // 默认我们采用eat();    
   drind() {
    console.log("喝水")
   }
}

class Man extends Person {
    play:() => void = () => {}
    eat():void {
        throw new Error("methods not implement");
    }
}

export {}

